// 元素配置
import type {
  ElementIdentifierId,
  ElementIdentifierResult,
} from '../../element/service/element_identifier/types'
import type {
  ElementHideConfig,
  ElementHideCssOperation,
  ElementLocator,
} from '../../element/service/types'
import type { InjectorType } from '../../lib/style_injector'
import type { ELEMENT_HIDE_TYPE, ELEMENT_SAVE_CONFIG, ElementConfigSource } from './base'
import { ElementIdentifier } from '../../element/service/element_identifier'

/**
 * 元素命名空间分隔符
 */
export const ELEMENT_NAMESPACE_SEPARATOR: string = ':'

/**
 * 事件发射器的事件名称
 */
export const EVENT_EMITTER_NAMES = {
  // 页面
  selectionChanged: 'page-selection-changed',
  urlChanged: 'page-url-changed',
  hideElement: 'page-hide-element',
  // 模块
  refreshQuickScroll: 'module-refresh-quick-scroll',
  refreshAdEngine: 'module-refresh-ad-engine',
}

export interface ElementCategoriesItemConfig {
  [identifier: string]: ElementConfig
}

export interface ElementCategoriesConfig {
  [hostname: string]: ElementCategoriesItemConfig
}

export interface TagCategoriesConfig {
  [platform: string]: {
    [identifier: string]: ElementTagConfig
  }
}

export enum ElementSelectorDOMScopeType {
  Document = 'document',
  ShadowRoot = 'shadow-root',
  Iframe = 'iframe',
  CrossFramework = 'cross-framework',
}

export enum ElementSelectorType {
  Id = 'id', // 单个 ID
  Class = 'class', // 单个类名
  Tag = 'tag', // 单个标签名
  Attribute = 'attribute', // 属性选择器： [name="value"]
  Mix = 'mix', // 混合选择器，例如：.class #id
  Multiple = 'multiple', // 多个选择器，例如：.class1, .class2
  Complex = 'complex', // 复杂选择器： .class > div + span
  JQuery = 'jquery', // jQuery 选择器
}

export enum ElementSelectorPosition {
  TopLeft = 'top-left',
  TopCenter = 'top-center',
  TopRight = 'top-right',
  MiddleLeft = 'middle-left',
  MiddleCenter = 'middle-center',
  MiddleRight = 'middle-right',
  BottomLeft = 'bottom-left',
  BottomCenter = 'bottom-center',
  BottomRight = 'bottom-right',
  Undefined = 'undefined',
}

export enum ElementSelectorContentSourceType {
  Official = 'official',
  Custom = 'custom',
}

export enum ElementSelectorCompoundQueryScope {
  Siblings = 'siblings', // 兄弟元素
  All = 'all', // 所有元素
  Children = 'children', // 子元素
  Descendants = 'descendants', // 后代元素（子元素及更深层级）
  Parent = 'parent', // 父元素
  Ancestors = 'ancestors', // 祖先元素
  Next = 'next', // 下一个兄弟元素
  Previous = 'previous', // 上一个兄弟元素
  Closest = 'closest', // 最近的匹配元素
  AllSiblings = 'all-siblings', // 所有兄弟元素（包括自身）
  NextSiblings = 'next-siblings', // 直到匹配选择器的所有下一个兄弟元素
  PreviousUntil = 'previous-until', // 直到匹配选择器的所有上一个兄弟元素
  ParentsUntil = 'parent-until', // 直到匹配选择器的所有祖先元素
}

export interface ElementSelectorCompoundOptions {
  attr: string
  value: string
  scope?: ElementSelectorCompoundQueryScope
}
export interface ElementSelectorListenOptions {
  timeout?: number
}

/**
 * 元素隐藏规则配置
 */
export type ElementHiderRuleConfig = Partial<Record<ElementIdentifierId, ElementConfig>>

export interface ElementConfig {
  enable?: boolean | (() => boolean)
  show?: boolean | (() => boolean)
  hide?: boolean
  domScope?: ElementSelectorDOMScopeType
  selectorType: ElementSelectorType
  hostSelector?: string
  selector: string
  nameZh?: string
  nameEn?: string
  position?: ElementSelectorPosition
  notExistsHide?: boolean
  effectToc?: boolean
  clearChildStyles?: boolean
  compoundOptions?: ElementSelectorCompoundOptions
  listen?: boolean
  listenOptions?: ElementSelectorListenOptions
  useCssInjection?: boolean
  handler?: () => void
  contentSource?: ElementSelectorContentSourceType
  metadata?: ElementIdentifierResult
}

export type ProcessedElementConfig = {
  [K in keyof ElementConfig]: K extends 'enable' | 'show'
    ? boolean // 将函数类型转换为 boolean
    : K extends 'compoundOptions' | 'listenOptions' | 'handler'
      ? ElementConfig[K] // 保持可选属性
      : NonNullable<ElementConfig[K]> // 其他属性变为必填
}

// 元素配置
export type ElementTagConfig = Omit<ElementConfig, 'selector' | 'effectToc' | 'type' | 'compoundOptions'> & {
  tag?: string
  hideParentSiblings?: boolean
}

export type ProcessedElementTagConfig = {
  [K in keyof ElementTagConfig]: K extends 'enable' | 'show'
    ? boolean // 将函数类型转换为 boolean
    : K extends | 'listenOptions' | 'handler'
      ? ElementTagConfig[K] // 保持可选属性
      : NonNullable<ElementTagConfig[K]> // 其他属性变为必填
}

// 元素插入位置
export enum InsertPosition {
  Before = 'before',
  After = 'after',
  Prepend = 'prepend',
  Append = 'append',
}

/**
 * 元素隐藏类型
 */
export type ElementHideType = typeof ELEMENT_HIDE_TYPE[keyof typeof ELEMENT_HIDE_TYPE]

/**
 * 元素保存类型
 */
export type ElementSaveType = typeof ELEMENT_SAVE_CONFIG[keyof typeof ELEMENT_SAVE_CONFIG]['id']

/**
 * 元素隐藏选项
 */
export interface HideElementOptions {
  /**
   * DOM 范围类型
   */
  domScope?: ElementSelectorDOMScopeType
  /**
   * 主机选择器（用于限制隐藏范围）
   */
  hostSelector?: string
  /**
   * 是否清除子元素的内联样式
   */
  clearChildStyles?: boolean
  /**
   * 复合选择器选项
   */
  compoundOptions?: ElementSelectorCompoundOptions
  /**
   * 隐藏类型
   */
  type?: ElementHideType
  /**
   * 白名单选择器（元素或祖先元素匹配时不隐藏）
   */
  whiteList?: string[]
  /**
   * 是否检查祖先元素是否在白名单中
   */
  checkAncestors?: boolean
}
/**
 * 元素隐藏选项
 */
export interface ElementDealOptions extends ElementHideConfig {
  selectorType: ElementSelectorType
  hostSelector: string
  selector: string
  name: string
  type: ElementSaveType
  clearChildStyles: boolean
  compoundOptions?: ElementSelectorCompoundOptions
  listenOptions?: ElementSelectorListenOptions
  source: ElementConfigSource
}

export interface IElementCSSOption {
  name: string
  domScope: ElementSelectorDOMScopeType
  selectorType: ElementSelectorType
  hostSelector?: string
  selector: string
  source: ElementConfigSource
  injectorType?: InjectorType
  operation: ElementHideCssOperation
}
export type ElementCSSIdOption = ElementLocator
export type ElementCSSStyleIdOption = Pick<IElementCSSOption, 'domScope' | 'hostSelector'>

export type ExtendedElementConfigProps = {
  [K in keyof Omit<ElementConfig, 'nameZh' | 'listenOptions' | 'handler'>]: K extends 'enable' | 'show'
    ? boolean
    : K extends 'compoundOptions' | 'listenOptions' | 'handler'
      ? ElementConfig[K] // 保持可选属性
      : NonNullable<ElementConfig[K]> // 其他属性变为必填且非空
} & {
  hideParentSiblings: boolean
}

export const DEFAULT_ELEMENT_CONFIG_VALUES: ExtendedElementConfigProps = {
  enable: true,
  show: true,
  hide: false,
  domScope: ElementSelectorDOMScopeType.Document,
  selectorType: ElementSelectorType.JQuery,
  hostSelector: '',
  selector: '',
  nameEn: '',
  position: ElementSelectorPosition.Undefined,
  notExistsHide: false,
  hideParentSiblings: false,
  effectToc: false,
  clearChildStyles: false,
  listen: false,
  compoundOptions: undefined,
  useCssInjection: true,
  contentSource: ElementSelectorContentSourceType.Official,
}

function createBaseConfig<T extends ElementConfig | ElementTagConfig>(
  identifier: string,
  config: T,
) {
  const enable = typeof config.enable === 'function' ? config.enable() : config.enable ?? DEFAULT_ELEMENT_CONFIG_VALUES.enable
  const show = typeof config.show === 'function' ? config.show() : config.show ?? DEFAULT_ELEMENT_CONFIG_VALUES.show

  const elementIdentifier = ElementIdentifier.getInstance()
  const identifierParts = identifier.split(ELEMENT_NAMESPACE_SEPARATOR)
  const metadata = config.metadata ?? elementIdentifier.api.getElement(identifierParts.length > 1 ? identifierParts[1] : identifierParts[0])

  return {
    enable,
    show,
    hide: config.hide ?? DEFAULT_ELEMENT_CONFIG_VALUES.hide,
    domScope: config.domScope ?? DEFAULT_ELEMENT_CONFIG_VALUES.domScope!,
    selectorType: config.selectorType ?? DEFAULT_ELEMENT_CONFIG_VALUES.selectorType,
    hostSelector: config.hostSelector ?? DEFAULT_ELEMENT_CONFIG_VALUES.hostSelector,
    nameZh: config.nameZh ?? metadata?.name,
    nameEn: config.nameEn ?? metadata?.eName ?? identifier,
    position: config.position ?? DEFAULT_ELEMENT_CONFIG_VALUES.position,
    notExistsHide: config.notExistsHide ?? DEFAULT_ELEMENT_CONFIG_VALUES.notExistsHide,
    clearChildStyles: config.clearChildStyles ?? DEFAULT_ELEMENT_CONFIG_VALUES.clearChildStyles,
    listen: config.listen ?? DEFAULT_ELEMENT_CONFIG_VALUES.listen,
    listenOptions: config.listenOptions,
    useCssInjection: config.useCssInjection ?? DEFAULT_ELEMENT_CONFIG_VALUES.useCssInjection,
    handler: config.handler,
  }
}

export function createElementConfig(identifier: string, config: ElementConfig): ProcessedElementConfig {
  const base = createBaseConfig(identifier, config)
  return {
    ...base,
    selector: config.selector || identifier,
    effectToc: config.effectToc ?? DEFAULT_ELEMENT_CONFIG_VALUES.effectToc,
    compoundOptions: config.compoundOptions,
    contentSource: config.contentSource ?? DEFAULT_ELEMENT_CONFIG_VALUES.contentSource,
  }
}

export function createElementTagConfig(identifier: string, config: ElementTagConfig): ProcessedElementTagConfig {
  const base = createBaseConfig(identifier, config)
  return {
    ...base,
    tag: config.tag || identifier,
    hideParentSiblings: config.hideParentSiblings ?? DEFAULT_ELEMENT_CONFIG_VALUES.hideParentSiblings,
  }
}
